/*
 * TCSS 422 - Spring quarter 2011
 * Team: 	Googlers
 * Members: Deepa Sahni, Krisnil Gounder, Michael Schweiger
 * Date: 	April 7, 2011
 */
package buffers;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * A generic buffer that regulates elements.  This class is thread safe.
 * @author Michael Schweiger
 * @version 1.0
 * @param <T> The data type that this buffer will hold.
 */
public class Buffer<T> {
	
	/**
	 * The queue to hold the elements (of type T)
	 */
	private final List<T> my_queue;
	
	/**
	 * Determines whether or not NULL values are allowed.
	 */
	private final boolean nulls_allowed;
	
	/**
	 * Constructor that initializes using the parameters given.  The list elements
	 * are copied.
	 * @throws IllegalArgumentException if the_list is null.
	 * @param the_list the_list The list to hold the elements, may not be null.
	 * @param can_have_nulls The boolean value of whether or not nulls are allowed.
	 */
	public Buffer(final List<T> the_list, final boolean can_have_nulls) 
		throws IllegalArgumentException {
		if (the_list == null) {
			throw new IllegalArgumentException("The list parameter cannot be null");
		}
		my_queue = new LinkedList<T>();
		Iterator<T> itr = the_list.iterator();
		while (itr.hasNext()) {
			my_queue.add(itr.next());
		}
		nulls_allowed = can_have_nulls;
	}
	
	/**
	 * Default constructor that uses a linked list and allows nulls.
	 */
	public Buffer() {
		my_queue = new LinkedList<T>();
		nulls_allowed = true;
	}
	
	/**
	 * Constructor that uses a linked list and nulls are determined by parameter.
	 * @param can_have_nulls Whether or not nulls are allowed.
	 */
	public Buffer(final boolean can_have_nulls) {
		my_queue = new LinkedList<T>();
		nulls_allowed = can_have_nulls;
	}
	
	/**
	 * Adds an element of type T to this buffer.
	 * @throws IllegalArgumentException if the_element is null and nulls aren't allowed.
	 * @param the_element The element to add
	 */
	public synchronized boolean add(final T the_element) throws IllegalArgumentException {
		if (the_element == null && !nulls_allowed) {
			throw new IllegalArgumentException("Nulls are not allowed!");
		}
		my_queue.add(the_element);
		return true;
	}
	
	/**
	 * Removes the element at the front of the buffer.
	 * @throws IllegalStateException if the buffer is empty.
	 */
	public synchronized T remove() throws IllegalStateException {
		if (my_queue.isEmpty()) {
			throw new IllegalStateException("The buffer is empty!");
		}
		return my_queue.remove(0);
	}
	
	/**
	 * @return The number of elements currently in the buffer
	 */
	public synchronized int getSize() {
		return my_queue.size();
	}
	
	/**
	 * Returns whether or not the buffer is empty.
	 * @return true if the buffer is empty, false otherwise.
	 */
	public synchronized boolean isEmpty() {
		return my_queue.isEmpty();
	}
	
	/**
	 * Returns whether nulls are allowed or not.
	 * @return true if nulls are allowed, false otherwise.
	 */
	public boolean nullsAllowed() {
		return nulls_allowed;
	}
}
